websocket @ServerEndpoint(value = "/websocket/{ip}")详解 您所在的位置:网站首页 websocket sendobject websocket @ServerEndpoint(value = "/websocket/{ip}")详解

websocket @ServerEndpoint(value = "/websocket/{ip}")详解

2023-03-20 16:25| 来源: 网络整理| 查看: 265

WebSocket是JavaEE7新支持的:

    Javax.websocket.server包含注解,类,接口用于创建和配置服务端点

    Javax.websocket包则包含服务端点和客户断电公用的注解,类,接口,异常

    创建一个编程式的端点,需要继承Endpoint类,重写它的方法。

    创建一个注解式的端点,将自己的写的类以及类中的一些方法用前面提到的包中的注解装饰(@EndPoint,@OnOpen等等)。

编程式注解示例:

@Component @ServerEndpoint(value = "/websocket/{ip}") public class MyWebSocket {   private static final Logger log = LoggerFactory.getLogger(MyWebSocket.class);   // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0;   // concurrent包的线程安全Map,用来存放每个客户端对应的MyWebSocket对象。 private static ConcurrentHashMap webSocketMap = new ConcurrentHashMap();   // 与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session;   private String ip; // 客户端ip public static final String ACTION_PRINT_ORDER = "printOrder"; public static final String ACTION_SHOW_PRINT_EXPORT = "showPrintExport";   /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("ip") String ip) { this.session = session; this.ip = ip; webSocketMap.put(ip, this); addOnlineCount(); // 在线数加1 // System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); log.info("有新连接加入,ip:{}!当前在线人数为:{}", ip, getOnlineCount()); ExportService es = BeanUtils.getBean(ExportService.class); List list = es.listExportCodesByPrintIp(ip); ResponseData rd = new ResponseData(); rd.setAction(MyWebSocket.ACTION_SHOW_PRINT_EXPORT); rd.setList(list); sendObject(rd); }   /** * 连接关闭调用的方法 */ @OnClose public void onClose(@PathParam("ip") String ip) { webSocketMap.remove(ip); // 从set中删除 // Map map = session.getPathParameters(); // webSocketMap.remove(map.get("ip")); subOnlineCount(); // 在线数减1 // System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); log.info("websocket关闭,IP:{},当前在线人数为:{}", ip, getOnlineCount()); }   /** * 收到客户端消息后调用的方法 * * @param message * 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) { // System.out.println("来自客户端的消息:" + message); log.debug("websocket来自客户端的消息:{}", message); OrderService os = BeanUtils.getBean(OrderService.class); OrderVo ov = os.getOrderDetailByOrderNo(message); // System.out.println(ov); ResponseData rd = new ResponseData(); ArrayList list = new ArrayList(); list.add(ov); rd.setAction(MyWebSocket.ACTION_PRINT_ORDER); rd.setList(list); sendObject(rd); // log.info("推送打印信息完成,单号:{}", ov.getOrderNo()); }   /** * 发生错误时调用 */ @OnError public void onError(Session session, Throwable error) { // System.out.println("发生错误"); log.error("webSocket发生错误!IP:{}", ip); error.printStackTrace(); }   /** * 像当前客户端发送消息 * * @param message * 字符串消息 * @throws IOException */ public void sendMessage(String message) { try { this.session.getBasicRemote().sendText(message); // this.session.getAsyncRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); log.error("发送数据错误,ip:{},msg:{}", ip, message); } }   /** * 向当前客户端发送对象 * * @param obj * 所发送对象 * @throws IOException */ public void sendObject(Object obj) { ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(Include.NON_NULL); String s = null; try { s = mapper.writeValueAsString(obj); } catch (JsonProcessingException e) { e.printStackTrace(); log.error("转json错误!{}", obj); } this.sendMessage(s); }   /** * 群发自定义消息 */ public static void sendInfo(String message) { for (Entry entry : webSocketMap.entrySet()) { MyWebSocket value = entry.getValue(); value.sendMessage(message); } }   public static synchronized int getOnlineCount() { return onlineCount; }   public static synchronized void addOnlineCount() { MyWebSocket.onlineCount++; }   public static synchronized void subOnlineCount() { MyWebSocket.onlineCount--; }   public static ConcurrentHashMap getWebSocketMap() { return webSocketMap; }   }

当创建好一个(服务)端点之后,将它以一个指定的URI发布到应用当中,这样远程客户端就能连接上它了。

Websocket(服务)端点以URI表述,有如下的访问方式:

ws://host:port/path?query

wss://host:port/path?query

注解详解:

@ServerEndPoint:

    RequiredElements :

        Value: URI映射

    OptionalElemens:

        subprotocols:

        decoders:解码器

        encoders:编码器

        configurator

建立连接相关:

Annotation

Event

Example

OnOpen

Connection opened

@OnOpen

Public void open(Sessionsession,

EndpointConfig conf) { }

OnMessage

Message received

@OnMessage

public void message(Sessionsession,

String msg) { }

OnError

Connection error

@OnError

public void error(Sessionsession,

Throwable error) { }

OnClose

Connection closed

@OnClose

public void close(Sessionsession,

CloseReason reason) { }

Session代表着服务端点与远程客户端点的一次会话。

容器会为每一个连接创建一个EndPoint的实例,需要利用实例变量来保存一些状态信息。

Session.getUserProperties提供了一个可编辑的map来保存properties,

例如,下面的端点在收到文本消息时,将前一次收到的消息回复给其他的端点

@ServerEndpoint("/delayedecho")   public class DelayedEchoEndpoint   {   @OnOpen   public void open(Sessionsession)   {   session.getUserProperties().put("previousMsg", "");   }       @OnMessage   public void message(Session session, Stringmsg)   {       String prev= (String) session.getUserProperties().get("previousMsg");       session.getUserProperties().put("previousMsg",msg);   try {   session.getBasicRemote().sendText(prev);       } catch (IOException e){ ... }   }   }

发送、接收消息:

Websocketendpoint能够发送和接收文本、二进制消息,另外,也可以发送ping帧和接收pong 帧

发送消息:

Obtain the Session object from theconnection.

从连接中获得Session对象

Session对象是endPoint中那些被注解标注的方法中可得到的参数

当你的message作为另外的消息的响应

在@OnMessage标注的方法中,有session对象接收message

如果你必须主动发送message,需要在标注了@OnOpen的方法中将session对象作为实例变量保存

这样,你可以再其他方法中得到该session对象

1.Use the Session object to obtain aRemote Endpoint object.

通过Session对象获得Remoteendpoint对象

2.Use the RemoteEndpoint object to sendmessages to the peer.

利用RemoteEndpoint对象来发送message

代码示例:

@ServerEndpoint("/echoall")

public class EchoAllEndpoint

{

@OnMessage

public void onMessage(Session session, Stringmsg)

{

try {

for (Session sess :session.getOpenSessions())

{

if (sess.isOpen())

sess.getBasicRemote().sendText(msg);

}

} catch (IOExceptione) { ... }

}

}

接收消息

OnMessage注解指定方法来处理接收的messages

在一个端点类中,至多可以为三个方法标注@OnMessage注解

消息类型分别为:text、binary、pong。

 

我们查看一下ServerEndpoint类源码:

@Retention(value = RetentionPolicy.RUNTIME) @Target(value = {ElementType.TYPE}) public @interface ServerEndpoint {   public String value();   public String[] subprotocols() default {};   public Class


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有